/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package grex;

import grex.genes.Gene;
import grex.genes.IPredictor;
import grex.genes.ITerminal;
import grex.genes.TargetPred;

import java.io.Serializable;

import java.util.Arrays;

/**
 *
 * @author RIK
 */
public class Prediction implements Serializable{
    private double[] instance;
    private double targetValue,prediction = 0,y;
    private boolean condition;
    private Gene  leaf;
    private double[] probs;
    
    public Prediction(double[] instance){
        this.instance = instance;
        targetValue = instance[instance.length-1];
    }

    private Prediction(Prediction p){
        this.instance = p.instance;
        this.leaf = p.leaf;
        this.targetValue=p.targetValue;
        this.condition=p.condition;
        if(p.probs!=null)
            probs = Arrays.copyOf(p.probs, p.probs.length);
        this.prediction=p.prediction;
        
    }
    
    //Normalizes the array and decouples it from the orignal array and sets the majority as the predicted class. Regression??
    //Other probabillity caculations like Laplace should be performed before the probs are set since they will remain unchanged if the sum is 1
    public void setProbsUsingSupport(double[] support){
        double sum=0,maxSupport=0;
        probs= new double[support.length];
        if(support.length==1){//Regression
            prediction = support[0];            
            return;
        }
        for(int i=0; i < probs.length;i++){
            sum+=support[i];
            if(support[i]>maxSupport){
                maxSupport = support[i];
                prediction = i;
            }
                    
        }
        for(int i=0; i < probs.length;i++){
            probs[i]=support[i]/sum;
        }
        
        leaf = null;
    }
    public void setProbs(double[] probs){
        this.probs = probs;//Arrays.copyOf(probs,probs.length);
        double maxSupport=0;
        if(probs.length==1){
            prediction=probs[0];
            return;
        }
        for(int i=0; i < probs.length;i++){
            if(probs[i]>maxSupport){
                maxSupport = probs[i];
                prediction = i;
            }                    
        }
    }

    public TargetPred getLeaf(){
        if(leaf==null)
            return null;
        return (TargetPred) leaf;
    }
    
    public Gene getL(){
        return leaf;
    }

    public double[] getProbs() {
        return probs;
    }
    
    public double getProbForClass(double c){
        return probs[(int)c];
    }

    public Prediction getCopy(){
        return new Prediction(this);
    }
    public double getTargetValue(){
      return targetValue;
        // return instance[instance.length-1];
    }

    public double[] getInstance() {
        return instance;
    }

    public double getPrediction() {
        return prediction;
    }

   public void setTargetValue(double value){
      // instance[instance.length-1] = value;
      targetValue=value;
    }

    public int getDepth(){
        return leaf.getNodeLevel();
    }

    public void setPrediction(double prediction) {
        this.prediction = prediction;
    }

    public void resetPredictionCalculations(){
   //     majority = -1;
        leaf = null;
        prediction = -1;
    }
    
  

    public double getProbabillity() {       
        return probs[(int)prediction];
    }

    public Gene getGene() {
        return leaf;
    }

    public void setLeaf(Gene leaf) {
        this.leaf = leaf;
    }

    public double getLowerProbabillity() {
        return ((ITerminal)leaf).getLowProb();
    }

    public void setProb(Double prob) {
        //this.prob = prob;
    }

    public void setLowerProb(double lowerProb) {
       // this.lowerProb = lowerProb;
    }

    public double[] getSupport() {
        //if(support != null)
        if(leaf==null)
            return probs;
        return ((TargetPred)leaf).support;
        //return support;
        //return missing;
    }

    public void setSupport(double[] support) {
        setProbsUsingSupport(support);

    }

    /**
     * @return the condition
     */
    public boolean getCondition() {
        return condition;
    }

    /**
     * @param condition the condition to set
     */
    public void setCondition(boolean condition) {
        this.condition = condition;
    }


}

